import { Injectable } from '@nestjs/common';
import { Response } from 'express';
import { ResultData } from 'src/common/utils/result';
import { ExportTable } from 'src/common/utils/export';
import { CreateConfigDto, UpdateConfigDto, ListConfigDto } from './dto/index';
import { RedisService } from 'src/module/common/redis/redis.service';
import { CacheEnum } from 'src/common/enum/index';
import { Cacheable, CacheEvict } from 'src/common/decorators/redis.decorator';
import { PrismaService } from '@/module/common/prisma/prisma.service';
import { pickEquals, pickLike } from '@/common/utils/prisma';

@Injectable()
export class ConfigService {
    constructor(
        private readonly redisService: RedisService,
        private readonly prisma: PrismaService
    ) { }
    async create(createConfigDto: CreateConfigDto) {
        await this.prisma.config.create({
            data: createConfigDto
        })
        return ResultData.ok();
    }

    async findAll(query: ListConfigDto) {
        let where: any = {
            delFlag: '0',
            ...pickLike(query, ['configName', 'configKey']),
            ...pickEquals(query, ['configType'])
        }
        if (query?.beginTime && query?.endTime) {
            where.createTime = {
                gte: new Date(query.beginTime),
                lte: new Date(query.endTime),
            }
        }
        const skip = query.pageSize && query.pageNum ? query.pageSize * (query.pageNum - 1) : undefined;
        const take = query.pageSize && query.pageNum ? +query.pageSize : undefined;
        const [list, total] = await Promise.all([
            this.prisma.config.findMany({
                where,
                skip,
                take,
            }),
            this.prisma.config.count({ where }),
        ]);

        return ResultData.ok({
            list,
            total,
        });
    }

    async findOne(configId: number) {
        const data = await this.prisma.config.findUnique({
            where: {
                configId
            }
        })
        return ResultData.ok(data);
    }

    async findOneByConfigKey(configKey: string) {
        const data = await this.getConfigValue(configKey);
        return ResultData.ok(data);
    }

    /**
     * 根据配置键值异步查找一条配置信息。
     *
     * @param configKey 配置的键值，用于查询配置信息。
     * @returns 返回一个结果对象，包含查询到的配置信息。如果未查询到，则返回空结果。
     */
    @Cacheable(CacheEnum.SYS_CONFIG_KEY, '{configKey}')
    async getConfigValue(configKey: string) {
        const data = await this.prisma.config.findFirst({
            where: {
                configKey
            }
        })
        return data.configValue;
    }

    async update(updateConfigDto: UpdateConfigDto) {
        await this.prisma.config.update({
            where: {
                configId: updateConfigDto.configId
            },
            data: updateConfigDto
        })
        return ResultData.ok();
    }

    async remove(configIds: number[]) {
        // 查询符合条件的记录
        const list = await this.prisma.config.findMany({
            where: {
                configId: { in: configIds }, // 使用 `in` 查询 configId 在 configIds 数组中的记录
                delFlag: '0', // 过滤 delFlag 为 '0' 的记录
            },
            select: {
                configType: true,
                configKey: true,
            },
        });

        // 检查是否存在内置参数
        const item = list.find((item) => item.configType === 'Y');
        if (item) {
            return ResultData.fail(500, `内置参数【${item.configKey}】不能删除`);
        }

        // 更新记录
        const data = await this.prisma.config.updateMany({
            where: {
                configId: { in: configIds }, // 更新 configId 在 configIds 数组中的记录
            },
            data: {
                delFlag: '1', // 更新 delFlag 为 '1'
            },
        });

        return ResultData.ok(data);
    }

    /**
     * 导出参数管理数据为xlsx
     * @param res
     */
    async export(res: Response, body: ListConfigDto) {
        delete body.pageNum;
        delete body.pageSize;
        const list = await this.findAll(body);
        const options = {
            sheetName: '参数管理',
            data: list.data.list,
            header: [
                { title: '参数主键', dataIndex: 'configId' },
                { title: '参数名称', dataIndex: 'configName' },
                { title: '参数键名', dataIndex: 'configKey' },
                { title: '参数键值', dataIndex: 'configValue' },
                { title: '系统内置', dataIndex: 'configType' },
            ],
            dictMap: {
                configType: {
                    Y: '是',
                    N: '否',
                },
            },
        };
        ExportTable(options, res);
    }

    /**
     * 刷新系统配置缓存
     * @returns
     */
    async resetConfigCache() {
        await this.clearConfigCache();
        await this.loadingConfigCache();
        return ResultData.ok();
    }

    /**
     * 删除系统配置缓存
     * @returns
     */
    @CacheEvict(CacheEnum.SYS_CONFIG_KEY, '*')
    async clearConfigCache() { }

    /**
     * 加载系统配置缓存
     * @returns
     */
    async loadingConfigCache() {
        const list = await this.prisma.config.findMany({
            where: {
                delFlag: '0'
            },
            select: {
                configKey: true,
                configValue: true,
            },
        })
        list.forEach((item) => {
            if (item.configKey) {
                this.redisService.set(`${CacheEnum.SYS_CONFIG_KEY}${item.configKey}`, item.configValue);
            }
        });
    }
}
